1
2
3
4 package joeq.ClassLib.Common.java.lang;
5
6 import java.util.HashMap;
7 import java.util.Map;
8 import java.io.ByteArrayInputStream;
9 import java.io.DataInputStream;
10 import java.security.ProtectionDomain;
11 import joeq.Class.PrimordialClassLoader;
12 import joeq.Class.jq_Array;
13 import joeq.Class.jq_Class;
14 import joeq.Class.jq_ClassFileConstants;
15 import joeq.Class.jq_CompiledCode;
16 import joeq.Class.jq_Reference;
17 import joeq.Class.jq_Type;
18 import joeq.Main.jq;
19 import joeq.Memory.StackAddress;
20 import joeq.Runtime.Reflection;
21 import joeq.Runtime.StackCodeWalker;
22 import joeq.UTF.Utf8;
23 import jwutil.util.Assert;
24
25 /***
26 * ClassLoader
27 *
28 * @author John Whaley <jwhaley@alum.mit.edu>
29 * @version $Id: ClassLoader.java 1941 2004-09-30 03:37:06Z joewhaley $
30 */
31 public abstract class ClassLoader {
32
33 private boolean initialized;
34 private java.lang.ClassLoader parent;
35 private static ClassLoader scl;
36
37
38 private final Map
39
40
41 void addClass(java.lang.Class c) {}
42
43
44 protected ClassLoader(java.lang.ClassLoader parent) {
45 java.lang.SecurityManager security = java.lang.System.getSecurityManager();
46 if (security != null) {
47 security.checkCreateClassLoader();
48 }
49 Assert._assert(parent != null);
50 this.parent = parent;
51 Map m = new HashMap();
52 this.desc2type = m;
53 this.initialized = true;
54 }
55 protected ClassLoader() {
56 java.lang.SecurityManager security = java.lang.System.getSecurityManager();
57 if (security != null) {
58 security.checkCreateClassLoader();
59 }
60 java.lang.ClassLoader parent = getSystemClassLoader();
61 Assert._assert(parent != null);
62 this.parent = parent;
63 Map m = new HashMap();
64 this.desc2type = m;
65 this.initialized = true;
66 }
67
68 native boolean isAncestor(ClassLoader cl);
69 static native RuntimePermission getGetClassLoaderPerm();
70 public native Class loadClass(java.lang.String name);
71
72
73 public static java.lang.ClassLoader getSystemClassLoader() {
74 java.lang.Object o = PrimordialClassLoader.loader;
75 scl = (ClassLoader)o;
76 if (scl == null) {
77 return null;
78 }
79 java.lang.SecurityManager sm = java.lang.System.getSecurityManager();
80 if (sm != null) {
81 ClassLoader ccl = getCallerClassLoader();
82 if (ccl != null && ccl != scl) {
83 try {
84 if (!scl.isAncestor(ccl)) {
85 sm.checkPermission(getGetClassLoaderPerm());
86 }
87 } catch (java.lang.Error x) {
88 throw x;
89 } catch (java.lang.Throwable x) {
90 Assert.UNREACHABLE();
91 }
92 }
93 }
94 o = scl;
95 return (java.lang.ClassLoader)o;
96 }
97
98
99 public java.lang.Class defineClass0(java.lang.String name, byte[] b, int off, int len,
100 ProtectionDomain pd) {
101
102 DataInputStream in = new DataInputStream(new ByteArrayInputStream(b, off, len));
103
104 if (name == null) throw new java.lang.ClassFormatError("name cannot be null when defining class");
105 if (name.startsWith("[")) throw new java.lang.ClassFormatError("cannot define array class with defineClass: "+name);
106 Utf8 desc = Utf8.get("L"+name.replace('.','/')+";");
107 if (this.getType(desc) != null)
108 throw new java.lang.ClassFormatError("class "+name+" already defined");
109 java.lang.Object o = this;
110 jq_Class c = jq_Class.newClass((java.lang.ClassLoader)o, desc);
111 Map desc2type = this.desc2type;
112 desc2type.put(desc, c);
113 c.load(in);
114
115 return Reflection.getJDKType(c);
116 }
117 private void resolveClass0(Class c) {
118 jq_Type t = c.jq_type;
119 t.load(); t.verify(); t.prepare();
120 }
121 private java.lang.Class findBootstrapClass(java.lang.String name) throws java.lang.ClassNotFoundException {
122 java.lang.Object o = PrimordialClassLoader.loader;
123 Assert._assert(this == o);
124 if (!name.startsWith("[")) name = "L"+name+";";
125 Utf8 desc = Utf8.get(name.replace('.','/'));
126 jq_Type k;
127 k = this.getOrCreateType(desc);
128 try {
129 k.load();
130 } catch (java.lang.ClassFormatError x) {
131
132 throw x;
133 } catch (java.lang.NoClassDefFoundError x) {
134 this.unloadType(k);
135 throw new java.lang.ClassNotFoundException(name);
136 }
137 return Reflection.getJDKType(k);
138 }
139 protected final java.lang.Class findLoadedClass(java.lang.String name) {
140 if (!name.startsWith("[")) name = "L"+name+";";
141 Utf8 desc = Utf8.get(name.replace('.','/'));
142 jq_Reference t = (jq_Reference) this.getType(desc);
143 if (t == null) return null;
144
145 if (t.getState() == jq_ClassFileConstants.STATE_UNLOADED)
146 t.load();
147 return Reflection.getJDKType(t);
148 }
149 static ClassLoader getCallerClassLoader() {
150 StackCodeWalker sw = new StackCodeWalker(null, StackAddress.getBasePointer());
151 sw.gotoNext(); sw.gotoNext(); sw.gotoNext();
152 jq_CompiledCode cc = sw.getCode();
153 if (cc == null) return null;
154 java.lang.Object o = cc.getMethod().getDeclaringClass().getClassLoader();
155 return (ClassLoader)o;
156 }
157
158
159 public jq_Type getType(Utf8 desc) {
160 Assert._assert(jq.RunningNative);
161 Map desc2type = this.desc2type;
162 jq_Type t = (jq_Type)desc2type.get(desc);
163 return t;
164 }
165 public static jq_Type getOrCreateType(java.lang.ClassLoader loader, Utf8 desc) {
166 java.lang.Object o = loader;
167 return ((ClassLoader)o).getOrCreateType(desc);
168 }
169 public jq_Type getOrCreateType(Utf8 desc) {
170 if (!jq.RunningNative)
171 return PrimordialClassLoader.loader.getOrCreateBSType(desc);
172 Map desc2type = this.desc2type;
173 jq_Type t = (jq_Type)desc2type.get(desc);
174 if (t == null) {
175 if (desc.isDescriptor(jq_ClassFileConstants.TC_CLASS)) {
176 java.lang.Object o = this;
177 t = jq_Class.newClass((java.lang.ClassLoader)o, desc);
178 } else {
179 if (!desc.isDescriptor(jq_ClassFileConstants.TC_ARRAY))
180 Assert.UNREACHABLE("bad descriptor! "+desc);
181 Utf8 elementDesc = desc.getArrayElementDescriptor();
182 jq_Type elementType;
183 elementType = this.getOrCreateType(elementDesc);
184 java.lang.Object o = this;
185 t = jq_Array.newArray(desc, (java.lang.ClassLoader)o, elementType);
186 }
187 desc2type.put(desc, t);
188 }
189 return t;
190 }
191 public void unloadType(jq_Type t) {
192 if (!jq.RunningNative) {
193 PrimordialClassLoader.loader.unloadBSType(t);
194 return;
195 }
196 Map desc2type = this.desc2type;
197 desc2type.remove(t.getDesc());
198 }
199
200 }